/**
 * Copyright 2009 University of  Washington
 * This code is released under the GPL version 3 - with a copy of the license included
 * @author Maya Hao Li
 *
 */
package seedpod.rdb;


import java.util.HashMap;

import seedpod.exceptions.SeedpodException;
import seedpod.kb2db.ModelMap;

/*
 * Manages a set of RDB connections. 
 * Each connection is correlated with a model map defined in the RDB itself. 
 */
public class PMFactory {
	private static PMFactory _instance = new PMFactory();
	private static RdbConnection _defaultRdbConnection;
	private final HashMap<String, RdbConnection> _namedRdbConnections;
	private final HashMap<RdbConnection, ModelMap> _namedModelMaps;

	private PMFactory() {
		_namedRdbConnections = new HashMap<String, RdbConnection>();
		_namedModelMaps = new HashMap<RdbConnection, ModelMap>();
	}

	public static PMFactory getInstance() {
		if ( _instance == null )
			_instance = new PMFactory();
		return _instance;
	}

	/**
	 * create a persistence manager using the application default connection if one is set else returns null
	 * 
	 * @return {@link RdbConnection}
	 */
	public PManager createManager() throws SeedpodException {
		if ( _defaultRdbConnection != null )
			return createManager( _defaultRdbConnection );
		else 
			throw new SeedpodException ("No default database connection defined");
	}

	public PManager createManager( RdbConnection connection ) {
		PManager manager = new PManager();
		addRdbConnection( connection );
		manager.setRdbConnection( connection );
		manager.setModelMap( getModelMap( connection ) );
		return manager;
	}
	
	public PManager createManager( RdbConnectParameters param ) {
		PManager manager = new PManager();
		manager.setRdbConnection( param );
		manager.setModelMap( getModelMap( manager.getRdbConnection() ) );
		return manager;
	}

	public PManager createManager( String databaseName ) {
		RdbConnection conn = getRdbConnection( databaseName );
		return createManager( conn );
	}


	public void addModelMap( RdbConnection conn, ModelMap map ) {
		_namedModelMaps.put( conn, map );
		if ( _defaultRdbConnection == null )
			_defaultRdbConnection = conn;
	}

	public ModelMap getModelMap( RdbConnection conn ) {
		ModelMap map = (ModelMap)_namedModelMaps.get( conn );
		// TODO if the map is null, download it
		return map;
	}

	public void addRdbConnection( RdbConnection connection ) {
		RdbConnectParameters param = connection.getRdbParameters();
		addRdbConnection( param.getDatabaseName(), connection );
	}

	public void setDefaultRdbConnection( RdbConnection connection ) {
		addRdbConnection( connection );
		_defaultRdbConnection = connection;
	}

	public RdbConnection getDefaultRdbConnection() {
		return _defaultRdbConnection;
	}

	public void addRdbConnection( String databaseName, RdbConnection connection ) {
		if ( !_namedRdbConnections.containsKey( databaseName ) )
			_namedRdbConnections.put( databaseName, connection );
	}

	public RdbConnection getRdbConnection( String databaseName ) {
		return (RdbConnection)_namedRdbConnections.get( databaseName );
	}

}
